package jpavlich.cardsorter.action;

import java.io.File;
import java.io.Serializable;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;

import jpavlich.cardsorter.Persistence;
import fr.inria.zvtm.animation.ActionTimingHandler;
import fr.inria.zvtm.animation.Animation;
import fr.inria.zvtm.engine.VirtualSpaceManager;

public class Experiment implements Serializable {
	enum State {
		STOPPED, RECORDING, PLAYING
	};
	
	private transient State state = State.STOPPED;

	private transient long recordTime;

	private Map<Long, Action<?>> actions = new TreeMap<Long, Action<?>>();
	
	private transient Persistence persistence;

	private File cardsFile;
	
	
	public Experiment(Persistence persistence, File cardsFile) {
		super();
		this.persistence = persistence;
		this.cardsFile = cardsFile;
	}

	public boolean execute(Action<?> a, boolean cloneAction) {
		Action<?> action = a;
		if (cloneAction) {
			action = a.clone();
		}
		long startTime = System.currentTimeMillis();
		action.execute();
		long duration = System.currentTimeMillis() - startTime;
		if (action.recordable && state == State.RECORDING) {
			long relativeStartTime = startTime - recordTime;
			action.setTime(relativeStartTime, duration);
			actions.put(relativeStartTime, action);
//			System.out.println("Rec: " + action);
			return true;
		} else {
			return false;
		}
	}

	public void stop() {
		state = State.STOPPED;
		System.out.println("Stop");
	}

	public void play() {
		System.out.println("Play");
		state = State.PLAYING;
		TreeMap<Long, Animation> animations = new TreeMap<Long, Animation>();
		for (Long t : actions.keySet()) {
			Action<?> a = actions.get(t);
			if (a != null) {
				Animation anim = a.createAnimation();
				if (anim != null) {
					animations.put(t, anim);
				}
			}
		}
		ActionTimeManager timeMgr = new ActionTimeManager();
		for (Iterator<Long> it = animations.keySet().iterator(); it.hasNext();) {
			Long time = it.next();
			Animation anim1 = animations.get(time);
			Long time2 = animations.higherKey(time);
			if (time2 != null) {
				Animation anim2 = animations.get(time2);
				ActionTimingHandler.setEndAction(anim1, new AnimationEndAction(anim2, time2, timeMgr));
			}
		}
		if (!animations.isEmpty()) {
			System.out.println("Starting reproduction");
			timeMgr.setPlayStartTime(System.currentTimeMillis());
			VirtualSpaceManager.INSTANCE.getAnimationManager().startAnimation(animations.firstEntry().getValue(), false);
		}
	}

	public void record() {
		System.out.println("Record");

		state = State.RECORDING;
		actions.clear();
		recordTime = System.currentTimeMillis();
	}

	public boolean isRecording() {
		return state == State.RECORDING;
	}

	public File getCardsFile() {
		return cardsFile;
	}

	public Persistence getPersistence() {
		return persistence;
	}

	public void setPersistence(Persistence persistence) {
		this.persistence = persistence;	
	}

	
	

}
